﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using TpBaseObjects.Interfaces;

namespace TpBaseObjects.Base {

    public class MyBaseModel : INotifyPropertyChanged, IBaseObject {

        #region Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Constructor

        public MyBaseModel() {

        }

        #endregion

        #region Methods

        protected void OnPropertyChanged<T>(Expression<Func<T>> name) {
            var propertyName = ExtractPropertyName(name);
            OnPropertyChanged(propertyName.ToString());
        }

        // Create the OnPropertyChanged method to raise the event 
        protected void OnPropertyChanged(string name) {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

        #endregion

        #region Functions

        private string ExtractPropertyName<T>(Expression<Func<T>> eigenschaftsAusdruck) {
            if (eigenschaftsAusdruck == null) {
                throw new ArgumentNullException("eigenschaftsAusdruck");
            }

            var memberExpression = eigenschaftsAusdruck.Body as MemberExpression;
            if (memberExpression == null) {
                throw new ArgumentException("Der Ausdruck ist kein Member-Lamda-Ausdruck (MemberExpression).", "eigenschaftsAusdruck");
            }

            var property = memberExpression.Member as PropertyInfo;
            if (property == null) {
                throw new ArgumentException("Der Member-Ausdruck greift nicht auf eine Eigenschaft zu.", "eigenschaftsAusdruck");
            }

            if (!property.DeclaringType.IsAssignableFrom(this.GetType())) {
                throw new ArgumentException("Die referenzierte Eigenschaft gehört nicht zum gewünschten Typ.", "eigenschaftsAusdruck");
            }

            var getMethod = property.GetGetMethod(true);
            if (getMethod == null) {
                // das sollte nicht auftreten ...
                throw new ArgumentException("Die referenzierte Eigenschaft hat keine 'get' - Methode.", "eigenschaftsAusdruck");
            }

            if (getMethod.IsStatic) {
                throw new ArgumentException("Die refrenzierte Eigenschaft ist statisch.", "eigenschaftsAusdruck");
            }

            return memberExpression.Member.Name;
        }

        #endregion

    }
}
